#!/bin/bash
#######################################
# Redis 主节点健康检查脚本（适配哨兵模式）
# 退出码：0=本机是主节点（健康），1=非主节点/异常
#######################################
# 配置参数（根据实际环境修改）
SENTINEL_IPS=("192.168.95.114" "192.168.95.115" "192.168.95.116")  # 3个哨兵IP，按优先级排序
SENTINEL_PORT="26379"          # 哨兵端口
REDIS_PASSWORD="Yqt#1234"      # Redis主从+哨兵的统一密码
CLUSTER_NAME="mymaster"        # 哨兵监控的集群名（与哨兵配置一致）
REDIS_CLI="/usr/local/redis/bin/redis-cli"  # redis-cli绝对路径
NETWORK_CARD="ens160"           # 本机网卡名称（用 ip addr 查看）
CURRENT_MASTER_IP=""            # 存储主节点IP，初始为空

# 1. 验证 redis-cli 是否存在
if [ ! -f "$REDIS_CLI" ]; then
    echo "ERROR: redis-cli 路径不存在" >> /var/log/check_redis.log 2>&1
    exit 1
fi

# 2. 从哨兵获取当前主节点IP（3秒超时，避免阻塞）
for ip in "${SENTINEL_IPS[@]}"; do
    # 尝试连接当前哨兵，获取主节点IP（3秒超时，屏蔽警告）
    master_ip=$($REDIS_CLI -h $ip -p $SENTINEL_PORT -a $REDIS_PASSWORD \
        SENTINEL get-master-addr-by-name $CLUSTER_NAME 2>/dev/null | head -n 1)
    
    # 若获取到有效IP（非空），则赋值并退出循环
    if [ -n "$master_ip" ] && [[ "$master_ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
        CURRENT_MASTER_IP=$master_ip
        break  # 找到可用哨兵，无需继续尝试
    fi
done

# 3. 若所有哨兵都连接失败，判定为异常
if [ -z "$CURRENT_MASTER_IP" ]; then
    echo "$(date +'%Y-%m-%d %H:%M:%S') - ERROR: 所有哨兵节点都无法连接" >> /var/log/check_redis.log 2>&1
    exit 1
fi

# /usr/local/redis/bin/redis-cli -h 192.168.95.116 -p 26379 -a Yqt#1234 SENTINEL get-master-addr-by-name mymaster 2>/dev/null

# 3. 获取本机业务IP（排除回环和虚拟IP）
LOCAL_IP=$(ip addr show $NETWORK_CARD | grep "inet " | awk '{print $2}' | cut -d '/' -f 1)

# 4. 对比当前主节点IP与本机IP（核心判断）
if [ -z "$CURRENT_MASTER_IP" ] || [ "$CURRENT_MASTER_IP" != "$LOCAL_IP" ]; then
    # 主节点IP为空（哨兵异常）或本机不是主节点 → 非健康
    echo "$(date +'%Y-%m-%d %H:%M:%S') - 本机IP: $LOCAL_IP, 当前主节点IP: $CURRENT_MASTER_IP → 非主节点" >> /var/log/check_redis.log 2>&1
    exit 1
else
    # 本机是主节点 → 健康
    echo "$(date +'%Y-%m-%d %H:%M:%S') - 本机IP: $LOCAL_IP, 当前主节点IP: $CURRENT_MASTER_IP → 主节点正常" >> /var/log/check_redis.log 2>&1
    exit 0
fi
